using System;
using System.Configuration;

namespace NWrapper.Config
{
	/// <summary>
	/// Represents a configuration element containing a collection of child elements of a given type.
	/// Generic version of <see cref="ConfigurationElementCollection"/>.
	/// </summary>
	/// <typeparam name="T">The configuration type. Must implement <see cref="ConfigurationElement"/>.</typeparam>
	[ConfigurationCollection(typeof(ConfigurationElement), CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
	public class ConfigurationElementCollection<T> : ConfigurationElementCollection where T : ConfigurationElement, new()
	{
		/// <summary>
		/// Creates a new <see cref="ConfigurationElement"/> of type <typeparamref name="T"/>. 
		/// </summary>
		/// <returns>A new <see cref="ConfigurationElement"/> of type <typeparamref name="T"/>.</returns>
		protected override ConfigurationElement CreateNewElement()
		{
			return new T();
		}

		/// <summary>
		/// Gets the element key for a specified configuration element when overridden in a derived class. 
		/// </summary>
		/// <param name="element">The <see cref="ConfigurationElement"/> to return the key for.</param>
		/// <returns>An object that acts as the key for the specified <see cref="ConfigurationElement"/>.</returns>
		protected override object GetElementKey(ConfigurationElement element)
		{
			return ((T)(element)).ToString();
		}

		/// <summary>
		/// Gets a <see cref="ConfigurationElement"/> object at the specified index location. 
		/// </summary>
		/// <param name="idx">The index location to return.</param>
		/// <returns>The <see cref="ConfigurationElement"/> at the specified index.</returns>
		public T this[int idx]
		{
			get
			{
				return (T)BaseGet(idx);
			}
		}

		/// <summary>
		/// Gets a <see cref="ConfigurationElement"/> object with the given key. 
		/// </summary>
		/// <param name="idx">The key of the item to return.</param>
		/// <returns>The <see cref="ConfigurationElement"/> with the given key.</returns>
		public new T this[string idx]
		{
			get
			{
				return (T)BaseGet(idx);
			}
		}

		/// <summary>
		/// Adds a <see cref="ConfigurationElement"/> to this collection.
		/// </summary>
		/// <param name="obj">The <see cref="ConfigurationElement"/> to add.</param>
		public void Add(T obj)
		{
			this.BaseAdd(obj);
		}
	}
}
